//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_review_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas-org/api-server/api_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/issue_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_review_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/requirement_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/testcase_dao"
	"atomgit.com/openlinksaas-org/api-server/dao/user_dao"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/notices/notices_project"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_review_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectReviewApiImpl) Create(ctx context.Context, req *project_review_api.CreateRequest) (*project_review_api.CreateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_review_api.CreateResponse{
			Code:   project_review_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_review_api.CreateResponse{
			Code:   project_review_api.CreateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_review_api.CreateResponse{
			Code:   project_review_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_review_api.CreateResponse{
			Code:   project_review_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_review_api.CreateResponse{
			Code:   project_review_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//过滤掉不存在的成员
	memberItemList, err := project_dao.MemberInfoDao.ListMemberById(ctx, req.ProjectId, req.MemberUserIdList)
	if err != nil {
		return nil, err
	}
	memberUserIdList := []string{}
	for _, memberItem := range memberItemList {
		memberUserIdList = append(memberUserIdList, memberItem.MemberUserId)
	}

	reviewId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_review_dao.ReviewDao.Insert(sessCtx, &project_review_dao.ReviewInfoDbItem{
			ReviewId:         reviewId,
			ProjectId:        req.ProjectId,
			Title:            req.Title,
			ReviewType:       uint32(req.ReviewType),
			Desc:             req.Desc,
			MemberUserIdList: memberUserIdList,
			CreateTime:       nowTime,
			UpdateTime:       nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &project_review_api.CreateResponse{
			Code:     project_review_api.CreateResponse_CODE_OK,
			ReviewId: reviewId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_project.CreateReviewNotice{
		ProjectId:    req.ProjectId,
		ReviewId:     reviewId,
		CreateUserId: sessionItem.UserId,
	})
	return ret.(*project_review_api.CreateResponse), nil
}

func (apiImpl *ProjectReviewApiImpl) ListSimple(ctx context.Context, req *project_review_api.ListSimpleRequest) (*project_review_api.ListSimpleResponse, error) {
	emptyList := []*project_review_api.SimpleReviewInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_review_api.ListSimpleResponse{
			Code:       project_review_api.ListSimpleResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			ReviewList: emptyList,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_review_api.ListSimpleResponse{
			Code:       project_review_api.ListSimpleResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			ReviewList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_review_api.ListSimpleResponse{
			Code:       project_review_api.ListSimpleResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			ReviewList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	count, err := project_review_dao.ReviewDao.CountSimple(ctx, req.ProjectId,
		req.FilterByReviewType, req.ReviewType, req.FilterByTitleKeyword, req.TitleKeyword)
	if err != nil {
		return nil, err
	}

	reviewItemList, err := project_review_dao.ReviewDao.ListSimple(ctx, req.ProjectId,
		req.FilterByReviewType, req.ReviewType, req.FilterByTitleKeyword, req.TitleKeyword,
		int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}

	//获取用户信息
	userIdList := []string{}
	for _, reviewItem := range reviewItemList {
		userIdList = append(userIdList, reviewItem.MemberUserIdList...)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	reviewList := []*project_review_api.SimpleReviewInfo{}

	for _, reviewItem := range reviewItemList {
		memberList := []*project_review_api.ReviewMemberItem{}
		for _, userId := range reviewItem.MemberUserIdList {
			userItem, ok := userItemMap[userId]
			if ok {
				memberList = append(memberList, &project_review_api.ReviewMemberItem{
					MemberUserId:      userId,
					MemberDisplayName: userItem.BasicInfo.DisplayName,
					MemberLogoUri:     userItem.BasicInfo.LogoUri,
				})
			}
		}

		reviewList = append(reviewList, &project_review_api.SimpleReviewInfo{
			ReviewId:   reviewItem.ReviewId,
			Title:      reviewItem.Title,
			ReviewType: project_review_api.REVIEW_TYPE(reviewItem.ReviewType),
			Desc:       reviewItem.Desc,
			MemberList: memberList,
			CreateTime: reviewItem.CreateTime,
			UpdateTime: reviewItem.UpdateTime,
		})
	}

	return &project_review_api.ListSimpleResponse{
		Code:       project_review_api.ListSimpleResponse_CODE_OK,
		TotalCount: count,
		ReviewList: reviewList,
	}, nil

}

func (apiImpl *ProjectReviewApiImpl) List(ctx context.Context, req *project_review_api.ListRequest) (*project_review_api.ListResponse, error) {
	emptyList := []*project_review_api.ReviewInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_review_api.ListResponse{
			Code:       project_review_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			ReviewList: emptyList,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_review_api.ListResponse{
			Code:       project_review_api.ListResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			ReviewList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_review_api.ListResponse{
			Code:       project_review_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			ReviewList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	count, err := project_review_dao.ReviewDao.Count(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}

	reviewItemList, err := project_review_dao.ReviewDao.List(ctx, req.ProjectId, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}
	reviewList, err := apiImpl.convertReviewList(ctx, req.ProjectId, reviewItemList)
	if err != nil {
		return nil, err
	}
	return &project_review_api.ListResponse{
		Code:       project_review_api.ListResponse_CODE_OK,
		TotalCount: count,
		ReviewList: reviewList,
	}, nil
}

func (apiImpl *ProjectReviewApiImpl) Get(ctx context.Context, req *project_review_api.GetRequest) (*project_review_api.GetResponse, error) {
	emptyInfo := &project_review_api.ReviewInfo{
		MemberList: []*project_review_api.ReviewMemberItem{},
		ResultList: []*project_review_api.ReviewResultItem{},
		LinkList:   []*project_review_api.ReviewLinkItem{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_review_api.GetResponse{
			Code:   project_review_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Review: emptyInfo,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_review_api.GetResponse{
			Code:   project_review_api.GetResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Review: emptyInfo,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_review_api.GetResponse{
			Code:   project_review_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Review: emptyInfo,
		}, nil
	} else if err != nil {
		return nil, err
	}

	reviewItem, err := project_review_dao.ReviewDao.Get(ctx, req.ProjectId, req.ReviewId)
	if err != nil {
		return nil, err
	}
	reviewList, err := apiImpl.convertReviewList(ctx, req.ProjectId, []*project_review_dao.ReviewInfoDbItem{reviewItem})
	if err != nil {
		return nil, err
	}
	return &project_review_api.GetResponse{
		Code:   project_review_api.GetResponse_CODE_OK,
		Review: reviewList[0],
	}, nil
}

func (apiImpl *ProjectReviewApiImpl) convertReviewList(ctx context.Context, projectId string, reviewItemList []*project_review_dao.ReviewInfoDbItem) ([]*project_review_api.ReviewInfo, error) {
	//补全成员信息
	reviewIdList := []string{}
	userIdList := []string{}
	for _, reviewItem := range reviewItemList {
		reviewIdList = append(reviewIdList, reviewItem.ReviewId)
		userIdList = append(userIdList, reviewItem.MemberUserIdList...)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//补全结果信息
	resultItemList, err := project_review_dao.ResultDao.List(ctx, projectId, reviewIdList)
	if err != nil {
		return nil, err
	}
	resultItemListMap := map[string][]*project_review_dao.ReviewResultItemDbItem{}
	for _, resultItem := range resultItemList {
		oldList := resultItemListMap[resultItem.ReviewId]
		if oldList == nil {
			oldList = []*project_review_dao.ReviewResultItemDbItem{}
		}
		oldList = append(oldList, resultItem)
		resultItemListMap[resultItem.ReviewId] = oldList
	}

	//补全链接信息
	linkItemList, err := project_review_dao.LinkDao.List(ctx, projectId, reviewIdList)
	if err != nil {
		return nil, err
	}
	linkItemListMap := map[string][]*project_review_dao.ReviewLinkItemDbItem{}
	entryIdList := []string{}
	reqIdList := []string{}
	issueIdList := []string{}
	tcIdList := []string{}

	for _, linkItem := range linkItemList {
		oldList := linkItemListMap[linkItem.ReviewId]
		if oldList == nil {
			oldList = []*project_review_dao.ReviewLinkItemDbItem{}
		}
		oldList = append(oldList, linkItem)
		linkItemListMap[linkItem.ReviewId] = oldList

		if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_CONTENT) ||
			linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_SPRIT) ||
			linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_DOC) ||
			linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_DRAW) ||
			linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_PAGES) ||
			linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_API_COLL) {
			entryIdList = append(entryIdList, linkItem.LinkTargetId)
		} else if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_REQUIREMENT) {
			reqIdList = append(reqIdList, linkItem.LinkTargetId)
		} else if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_BUG) || linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_TASK) {
			issueIdList = append(issueIdList, linkItem.LinkTargetId)
		} else if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_TEST_CASE) {
			tcIdList = append(tcIdList, linkItem.LinkTargetId)
		}
	}

	entryTitleMap := map[string]string{}
	reqTitleMap := map[string]string{}
	issueTitleMap := map[string]string{}
	tcTitleMap := map[string]string{}

	if len(entryIdList) > 0 {
		entryItemList, err := project_entry_dao.EntryDao.ListById(ctx, entryIdList)
		if err != nil {
			return nil, err
		}
		for _, entryItem := range entryItemList {
			entryTitleMap[entryItem.EntryId] = entryItem.EntryTitle
		}
	}
	if len(reqIdList) > 0 {
		reqItemList, err := requirement_dao.RequirementInfoDao.ListById(ctx, projectId, reqIdList)
		if err != nil {
			return nil, err
		}
		for _, reqItem := range reqItemList {
			reqTitleMap[reqItem.RequirementId] = reqItem.BaseInfo.Title
		}
	}
	if len(issueIdList) > 0 {
		issueItemList, err := issue_dao.IssueDao.ListById(ctx, projectId, issueIdList)
		if err != nil {
			return nil, err
		}
		for _, issueItem := range issueItemList {
			issueTitleMap[issueItem.IssueId] = issueItem.BasicInfo.Title
		}
	}
	if len(tcIdList) > 0 {
		tcItemList, err := testcase_dao.CaseInfoDao.ListById(ctx, projectId, tcIdList)
		if err != nil {
			return nil, err
		}
		for _, tcItem := range tcItemList {
			tcTitleMap[tcItem.CaseId] = tcItem.Title
		}
	}

	//生成结果
	reviewList := []*project_review_api.ReviewInfo{}
	for _, reviewItem := range reviewItemList {
		review := reviewItem.ToReviewInfo()
		//处理memberList
		for _, memberUserId := range reviewItem.MemberUserIdList {
			userItem, ok := userItemMap[memberUserId]
			if ok {
				review.MemberList = append(review.MemberList, &project_review_api.ReviewMemberItem{
					MemberUserId:      userItem.UserId,
					MemberDisplayName: userItem.BasicInfo.DisplayName,
					MemberLogoUri:     userItem.BasicInfo.LogoUri,
				})
			}
		}
		//处理结果列表
		resultItemList := resultItemListMap[reviewItem.ReviewId]
		for _, resultItem := range resultItemList {
			review.ResultList = append(review.ResultList, resultItem.ToReviewResultItem())
		}
		//处理链接列表
		linkItemList := linkItemListMap[reviewItem.ReviewId]
		for _, linkItem := range linkItemList {
			link := linkItem.ToReviewLinkItem()
			if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_CONTENT) ||
				linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_SPRIT) ||
				linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_DOC) ||
				linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_DRAW) ||
				linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_PAGES) ||
				linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_API_COLL) {
				link.LinkTitle = entryTitleMap[linkItem.LinkTargetId]
			} else if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_REQUIREMENT) {
				link.LinkTitle = reqTitleMap[linkItem.LinkTargetId]
			} else if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_BUG) || linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_TASK) {
				link.LinkTitle = issueTitleMap[linkItem.LinkTargetId]
			} else if linkItem.LinkType == uint32(project_review_api.LINK_TYPE_LINK_TYPE_TEST_CASE) {
				link.LinkTitle = tcTitleMap[linkItem.LinkTargetId]
			}
			review.LinkList = append(review.LinkList, link)
		}

		reviewList = append(reviewList, review)
	}

	return reviewList, err
}

func (apiImpl *ProjectReviewApiImpl) Remove(ctx context.Context, req *project_review_api.RemoveRequest) (*project_review_api.RemoveResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_review_api.RemoveResponse{
			Code:   project_review_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_review_api.RemoveResponse{
			Code:   project_review_api.RemoveResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_review_api.RemoveResponse{
			Code:   project_review_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_review_api.RemoveResponse{
			Code:   project_review_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_review_api.RemoveResponse{
			Code:   project_review_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := project_review_dao.ReviewDao.Exist(ctx, req.ProjectId, req.ReviewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_review_api.RemoveResponse{
			Code: project_review_api.RemoveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_review_dao.ReviewDao.Remove(sessCtx, req.ProjectId, req.ReviewId)
		if err != nil {
			return nil, err
		}
		err = project_review_dao.ResultDao.RemoveByReview(sessCtx, req.ProjectId, req.ReviewId)
		if err != nil {
			return nil, err
		}
		err = project_review_dao.LinkDao.RemoveByReview(sessCtx, req.ProjectId, req.ReviewId)
		if err != nil {
			return nil, err
		}
		return &project_review_api.RemoveResponse{
			Code: project_review_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_project.RemoveReviewNotice{
		ProjectId: req.ProjectId,
		ReviewId:  req.ReviewId,
	})
	return ret.(*project_review_api.RemoveResponse), nil
}

func (apiImpl *ProjectReviewApiImpl) UpdateBasic(ctx context.Context, req *project_review_api.UpdateBasicRequest) (*project_review_api.UpdateBasicResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_review_api.UpdateBasicResponse{
			Code:   project_review_api.UpdateBasicResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_review_api.UpdateBasicResponse{
			Code:   project_review_api.UpdateBasicResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_review_api.UpdateBasicResponse{
			Code:   project_review_api.UpdateBasicResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_review_api.UpdateBasicResponse{
			Code:   project_review_api.UpdateBasicResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_review_api.UpdateBasicResponse{
			Code:   project_review_api.UpdateBasicResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := project_review_dao.ReviewDao.Exist(ctx, req.ProjectId, req.ReviewId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_review_api.UpdateBasicResponse{
			Code:   project_review_api.UpdateBasicResponse_CODE_NO_REVIEW,
			ErrMsg: "复盘记录不存在",
		}, nil
	}

	//过滤掉不存在的成员
	memberItemList, err := project_dao.MemberInfoDao.ListMemberById(ctx, req.ProjectId, req.MemberUserIdList)
	if err != nil {
		return nil, err
	}
	memberUserIdList := []string{}
	for _, memberItem := range memberItemList {
		memberUserIdList = append(memberUserIdList, memberItem.MemberUserId)
	}

	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_review_dao.ReviewDao.Update(sessCtx, req.ProjectId, req.ReviewId, req.Title, req.ReviewType, req.Desc, memberUserIdList, nowTime)
		if err != nil {
			return nil, err
		}
		return &project_review_api.UpdateBasicResponse{
			Code: project_review_api.UpdateBasicResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_project.UpdateReviewNotice{
		ProjectId: req.ProjectId,
		ReviewId:  req.ReviewId,
	})
	return ret.(*project_review_api.UpdateBasicResponse), nil
}
